package com.gongj.hystrix.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheKey;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheRemove;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheResult;
import com.netflix.hystrix.contrib.javanica.command.AsyncResult;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.concurrent.Future;


/**
 * 基本用法
 */
@Service
public class HystrixService {

    @Autowired
    RestTemplate resTtemplate;

    /**
      * 在这个方法中，我们将发起一个远程调用，去调用 provider 中提供的 /hello 接口
      *
      * 但是，这个调用可能会失败。
      *
      * 我们在这个方法上添加 @HystrixCommand 注解，配置 fallbackMethod 属性，这个属性表示
        该方法调用失败时的临时替代方法
        名词:服务降级
      * @return
      */
    @HystrixCommand(fallbackMethod = "error",
            ignoreExceptions = {ArrayIndexOutOfBoundsException.class},
            commandKey = "getUsercommandKey",
            groupKey = "getUsergroupKey",
            threadPoolKey="getUserthreadPoolKey")
    public String getUser(){
        String result = resTtemplate.getForObject("http://appUser/api/user", String.class);
        return result;
    }

    //注解同步执行
    @HystrixCommand
    public String getName(){
        String result = resTtemplate.getForObject("http://appUser/api/user/getName?name={1}", String.class,"嘿嘿");
        return result;
    }

    //注解异步执行
    @HystrixCommand
    public Future<String> getName2(){
         return new AsyncResult<String>() {
             @Override
             public String invoke() {
                 String forObject = resTtemplate.getForObject("http://appUser/api/user/getName?name={1}", String.class, "嘿嘿22222");
                 return forObject;
             }
         };
    }
    /**
    * 注意，这个方法名字要和 fallbackMethod 一致
    * 方法返回值也要和对应的方法一致
    * @return
    */
    @HystrixCommand(fallbackMethod = "error1")
    public String error(){
        return resTtemplate.getForObject("http://appUser/api/user", String.class);
    }

    public String error1(Throwable t){

        return "error1" + t.getMessage();
    }




    //注解：请求缓存
    @HystrixCommand
    //@CacheResult(cacheKeyMethod = "cacheKey") //这个注解表示该方法的请求结果会被缓存起来，默认情况下，缓存的 key 就是方法的参
    //数，缓存的 value 就是方法的返回值。
    @CacheResult
    public String getName6(String name, @CacheKey Long id){
        String result = resTtemplate.getForObject("http://appUser/api/user/getName?name={1}", String.class,name);
        return result;
    }


    private String cacheKey(String name,Long id){
        return name;
    }

    @CacheRemove(commandKey = "getName6")
    @HystrixCommand
    public void flushCache(@CacheKey Long id){}
}
